﻿
using NLog;
using Sea;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Threading;
using UeyesAIS.DataDefinition;

namespace UeyesAIS.Service.ImageProcess
{
    public class ImageProcess
    {
        internal static EnumResult CorrectRlt = new EnumResult();
        private readonly ILogger _algprocess;
        private static readonly ILogger _logCamera = LogManager.GetCurrentClassLogger();
        public SeaPin Sp;//在主界面赋值，属于产品项目管理
        internal string cameraID;
        public DateTime start;
        private readonly ManualResetEvent _correctDone = new ManualResetEvent(false);
        private ManualResetEvent[] resultEvent;
        public ImageProcess(string cameraname)
        {
            cameraID = cameraname;
            _algprocess = LogManager.GetLogger("alg");
        }
        internal void InitAlgthom()
        {
            if (DeviceService.Intance.DefaultProduct == null) return;
            AlgDispose();
            Sp = new SeaPin();
        }
        [HandleProcessCorruptedStateExceptions]
        internal void AlgDispose()
        {
            try
            {
                if (Sp != null)
                    Sp.Dispose();
            }
            catch
            {
                // ignored
            }
        }
        #region 校正处理
        [HandleProcessCorruptedStateExceptions]
        public ResultDisplayRowResult InspCorrectPic(Bitmap bm)
        {
            CorrectRlt = EnumResult.None;
            ResultDisplayRowResult result = new ResultDisplayRowResult() { SourceName = cameraID };
            result.ItemName = "校正图";
            result.Index = 0;
            try
            {
                var correct = DeviceService.Intance.DefaultProduct.ParamList[Device.CorrectIndex].InspGroup.Find(x => x.InspMethods.Contains(0) || x.InspMethods.Contains(1) || x.InspMethods.Contains(2));
                var ret = 0;
                _algprocess.Trace("矫正开始");
                List<int> c = new List<int>(), r = new List<int>(), d = new List<int>(), v = new List<int>();
                BitmapData bitmapdata = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);//转化为灰度图30ms
                IntPtr ptrbitmap = (bitmapdata.Scan0);
                Sp.SetPara(correct.Sp);//传值
                ret = Sp.InspAll(ptrbitmap, bm.Width, bm.Height, correct.InspMethods.First(), r, c, v, d);
                _algprocess.Trace("矫正结束，结果：" + ret);
                if (ret == -1)//这里不正确的图片会死掉
                {
                    result.Msg = "NG";
                    result.Result = false;
                    CorrectRlt = EnumResult.Failed;
                }
                else
                {
                    result.Msg = "OK";
                    result.Result = true;
                    bm.UnlockBits(bitmapdata);//3ms
                    CorrectRlt = EnumResult.Pass;
                }
                result.InspedImg = bm;
                _correctDone.Set();
                Console.WriteLine("校正完成");
                GC.Collect();
                return result;
            }
            catch (Exception ex)
            {
                _logCamera.Error("矫正算法异常" + ex.Message);
                CorrectRlt = EnumResult.Failed;
                _correctDone.Set();
                return result;
            }
        }
        #endregion 图片校正

        #region 画面检
        /// <summary>
        /// 检测黑白灰RGB过程
        /// </summary>
        /// <param name="inspSouce"></param>
        [HandleProcessCorruptedStateExceptions]
        public ResultDisplayRowResult ThreadInspColorPic(object inspSouce)
        {
            var ii = inspSouce as InspImageInfo;
            var width = ii.ImgSouce[0].Width;
            var height = ii.ImgSouce[0].Height;
            bool isstep = ii.Step;
            ResultDisplayRowResult rowResult = new ResultDisplayRowResult() { SourceName = cameraID };
            rowResult.Index = ii.Index;//检测图索引
            var startpoint = start;
            try
            {
                var insppicitem = DeviceService.Intance.DefaultProduct.ParamList.Find(x => x.PicParameter.Picindex == rowResult.Index);
                rowResult.ItemName = string.Format("检：{0}", (insppicitem != null) ? insppicitem.PicParameter.Picname : ii.Index.ToString());
                var inspitem = insppicitem.InspGroup.Find(x => x.CameraName.Equals(cameraID));
                _logCamera.Trace(rowResult.ItemName + " 进入检测画面线程完成");
                var tempimage = (Bitmap)ii.ImgSouce[0].Clone();
                var timeout = true;
                if (!isstep)//非调试
                {
                    timeout = WaitHandle.WaitAll(resultEvent, 500000);
                }
                _logCamera.Trace("{0}开始处理,等待校正清灰{1}超时", rowResult.ItemName, timeout ? "未" : "已");
                var rows = new List<int>();
                var cols = new List<int>();
                var diffs = new List<int>();
                var values = new List<int>();
                var types = new List<int>();
                if (CorrectRlt.Equals(EnumResult.Pass))
                {
                    if (ii.Index < -5 || inspitem == null)
                        return rowResult;
                    var uniformity = false;
                    for (int i = 0; i < inspitem.InspMethods.Count; i++)
                    {
                        var image = (Bitmap)ii.ImgSouce[0].Clone();
                        BitmapData bitmapdata = image.LockBits(new Rectangle(0, 0, width, height),
                       ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); //转化为灰度图30ms
                        IntPtr ptrbitmap = (bitmapdata.Scan0);
                        var singlepic = Sp.Clone();
                        singlepic.SetPara(inspitem.Sp);

                        var methodindex = inspitem.InspMethods[i];
                        var r = new List<int>();
                        var c = new List<int>();
                        var v = new List<int>();
                        var d = new List<int>();
                        var t = new List<int>();
                        if (methodindex == 100 || methodindex == 101 || methodindex == 1 || methodindex == 2)
                            continue;
                        _logCamera.Trace("{0}，{1}项检测开始", rowResult.ItemName, methodindex);
                        var t2 = singlepic.InspAll(ptrbitmap, width, height, methodindex, c, r, t, v);
                        if (t2 < 0)
                        {
                            r.Add(1);
                            c.Add(1);
                            t.Add(1);
                            v.Add(1);
                        }
                        r.ForEach(x => d.Add(methodindex));
                        _logCamera.Trace("{0}，{1}项检测完成，结果：{2}", rowResult.ItemName, methodindex, t2);
                        //if (inspitem.PicParameter.IgAr.IsOpen && c.Count > 0)
                        //    RemoveArr(inspitem.PicParameter.IgAr, c, d, r, v, t);
                        uniformity = ((SelectedFuction)methodindex).GetHashCode() ==
                                        SelectedFuction.UniformityImage.GetHashCode();
                        cols.AddRange(c);
                        diffs.AddRange(d);
                        values.AddRange(v);
                        rows.AddRange(r);
                        types.AddRange(t);
                        image.UnlockBits(bitmapdata);
                        tempimage.Dispose();
                        tempimage = image;
                        singlepic.Dispose();
                        if (rows.Any() && !uniformity) //只要有NG即中止检测
                            break;
                    }
                    for (int j = 1; j < ii.ImgSouce.Count(); j++)
                    {
                        ii.ImgSouce[j].Dispose();
                        ii.ImgSouce[j] = null;
                    }
                    if (rowResult.InspedImg != null)
                        rowResult.InspedImg.Dispose();
                    var f1 = rows.Count == 0 && cols.Count == 0 && diffs.Count == 0 && values.Count == 0;
                    if (uniformity)
                    {
                        double pecent = 0;
                        if (values.Count > 1)
                        {
                            if (values[1] != 0)
                            {
                                pecent = Math.Round(values[0] / (double)values[1], 4) * 100;
                            }
                            else
                            {
                                pecent = 100;
                            }
                        }
                        var standard = inspitem.RParam.Find(x => x.ParamDescrition.Contains("均一性")).ParamValue;
                        if (pecent >= standard)
                        {
                            rowResult.Result = true;
                            rowResult.Msg = string.Format("OK({0}%)", pecent);
                        }
                        else
                        {
                            rowResult.Result = false;
                            rowResult.Msg = string.Format("NG({0}%)", pecent);
                        }
                    }
                    else if (f1)
                    {
                        rowResult.Result = true;
                        rowResult.Msg = "OK";
                    }
                    else
                    {
                        rowResult.Result = false;
                        rowResult.Msg = "NG";
                    }
                }
                else
                {
                    rowResult.Result = false;
                    rowResult.Msg = "CorrectFail";
                }
                Console.WriteLine("{0}  {1}检测完成", DateTime.Now.ToString("HH:mm:ss-ffff"), rowResult.ItemName);
                if (!startpoint.Equals(start))//防止串扰
                    return rowResult;
                rowResult.InspedImg = tempimage;
                rowResult.ErrCol = cols;
                rowResult.ErrRow = rows;
                rowResult.ErrType = types;
                rowResult.ErrValue = values;
                rowResult.ErrDiff = diffs;
                _logCamera.Trace("{0}全部检测完成", rowResult.ItemName);
                GC.Collect();
                return rowResult;
            }
            catch (Exception ex)
            {
                GC.Collect();
                _algprocess.Error("Camera=>{0}{1}", string.Format(cameraID + "异常信息：：{0}！", ex.Message + ex.TargetSite), string.Format("检测过程图片{0}异常", rowResult.ItemName));
            }
            return rowResult;
        }

        #endregion

        #region 仿射检测均值合格
        /// <summary>
        /// 仿射、均值计算
        /// </summary>
        /// <param name="ptrbitmap">图像指针</param>
        /// <param name="width">图像宽</param>
        /// <param name="height">图像高</param>
        /// <param name="itemname">图像名</param>
        /// <param name="mean">均值范围</param>
        /// <returns></returns>
        //private bool FangShe(IntPtr ptrbitmap, int width, int height, string itemname, MeanThresold mean)
        //{
        //    if (CorrectRlt.GetHashCode() != EnumResult.pass.GetHashCode())
        //    {
        //        _logCamera.Trace(itemname + " 未校正成功：" + CorrectRlt.ToString());
        //        return false;
        //    }
        //    var t1 = Sp.AlgMod.ApiInsp(ptrbitmap, width, height, 100, 0, new List<int>(), new List<int>(), new List<int>(), new List<int>());
        //    _logCamera.Trace(itemname + " 仿射图像操作完成：" + t1);
        //    if (t1 != 0) return false;
        //    _logCamera.Trace(itemname + " 仿射图像成功，开始计算均值");
        //    var meanlist = new List<int>();
        //    var tmean = Sp.AlgMod.ApiMean(ptrbitmap, width, height, meanlist);
        //    var meanflag = false;
        //    if (tmean == -1)
        //    {
        //        _logCamera.Trace("均值计算失败，返回值{0},meanlist个数：{1}", tmean, meanlist.Count);
        //    }
        //    else
        //    {
        //        meanflag = meanlist[0] >= mean.MeanMin && meanlist[0] < mean.MeanMax;
        //        _logCamera.Trace("{0} 计算均值完成：{1}，结果：{2}({3})，范围{4}～{5}", itemname, tmean, meanlist.Count > 0 ? meanlist[0] : -1, meanflag.ToString(), mean.MeanMin, mean.MeanMax);
        //    }
        //    if (t1 == 0 && meanflag)
        //        return true;
        //    return false;
        //}
        #endregion

        #region 边缘屏蔽


        void RemoveArr(IgnoseArea ig, List<int> c, List<int> diff, List<int> r, List<int> v, List<int> type)
        {
            var correct = DeviceService.Intance.DefaultProduct.ParamList[Device.CorrectIndex].InspGroup.Find(x => x.CameraName.Equals(cameraID));
            double up = ig.Upedge;
            double down = correct.Sp.LCDPixelHeight * correct.Sp.PixelInterval - ig.Downedge;
            double left = ig.Leftedge;
            double right = correct.Sp.LCDPixelWidth * correct.Sp.PixelInterval - ig.Rightedge;
            if (ig.Downedge != 0 || ig.Rightedge != 0 || ig.Upedge != 0 || ig.Leftedge != 0)
                for (int i = r.Count - 1; i >= 0; i--)
                {
                    if (r[i] > down || c[i] > right || r[i] < up || c[i] < left)
                    {
                        r.RemoveAt(i);
                        c.RemoveAt(i);
                        diff.RemoveAt(i);
                        v.RemoveAt(i);
                        type.RemoveAt(i);
                    }
                }
        }
        #endregion 边缘屏蔽

        #region 除灰处理

        /// <summary>
        /// 算法除灰 ResultDisplayRowResult
        /// </summary>
        /// <param name="bm"></param>
        /// <param name="index"></param>
        internal ResultDisplayRowResult InspDustPic(Bitmap bm, int index)
        {
            var rowResult = new ResultDisplayRowResult { ItemName = "初始值", SourceName = cameraID };
            try
            {
                _logCamera.Trace("清灰{0}开始", index);
                var msg = "";
                var picindx = DeviceService.Intance.DefaultProduct.ParamList.FindIndex(x => x.PicParameter.Picindex == index - 3);
                if (picindx < 0)
                    return rowResult;
                var picitem = DeviceService.Intance.DefaultProduct.ParamList[picindx];
                rowResult.ItemName = picitem.PicParameter.Picname;
                var item = picitem.InspGroup.Find(x => x.CameraName.Equals(cameraID));
                int width = bm.Width;
                int height = bm.Height;
                var bitmapdata = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadWrite,
                    PixelFormat.Format8bppIndexed); //转化为灰度图30ms
                var ptrbitmap = (bitmapdata.Scan0);
                if (!CorrectRlt.Equals(EnumResult.Pass))
                {
                    msg = "DustFailed";
                    rowResult.Result = false;
                }
                else
                {
                    var cmdindex = 3;
                    Sp.SetPara(item.Sp);//传值
                    var calresult = Sp.InspAll(ptrbitmap, bm.Width, bm.Height, item.InspMethods.First(), new List<int>(), new List<int>(), new List<int>(), new List<int>());
                    msg = "OK";
                    rowResult.Result = calresult >= 0;
                    msg = rowResult.Result ? "OK" : "NG";
                    _logCamera.Trace("清灰{0},算子{1},计算结果{2}", index, cmdindex, calresult);
                }
                _logCamera.Trace("清灰{0}完成,结果{1}", index);
                bm.UnlockBits(bitmapdata);//3ms
                rowResult.InspedImg = (Bitmap)bm.Clone();
                rowResult.Index = index + 33;
                rowResult.Msg = msg;
                bm.Dispose();
                bm = null;
                Console.WriteLine("清灰完成{0}", index);
                resultEvent[index].Set();
            }
            catch (Exception ex)
            {
                resultEvent[index].Set();
                _logCamera.Error("Camera=>CameraInsp-InspDustPicError：除尘{0}\r\n{1}", index, ex.Message);
            }
            return rowResult;
        }
        #endregion 算法除灰
        internal void Refresh()
        {
            resultEvent = new ManualResetEvent[DeviceService.Intance.DefaultProduct.ParamList.Count(x => x.PicParameter.Picindex == -2 || x.PicParameter.Picindex == -3)];
            start = DateTime.Now;
            for (int i = 0; i < resultEvent.Length; i++)
            {
                if (resultEvent[i] == null)
                    resultEvent[i] = new ManualResetEvent(false);
                else
                    resultEvent[i].Reset();
            }
            CorrectRlt = EnumResult.None;
            _correctDone.Reset();
        }
    }
}
